#pragma once

#include <string>

#include <engine.core/Cache.hpp>

#include "Widget.hpp"




namespace Engine
{
	namespace Ui
	{
		/**
		 * The text class (obviously) represents a text on the Ui.
		 */
		class ENGINE_UI_API Text
			: public Widget
		{
		public:

			SHARED(Text);

		protected:

			/**
			 * Create a Text Widget.
			 */
			Text(const QString& text, Widget::weak_ptr parent);
			virtual void post_create(ptr _this);

		public:

			MAKE_SHARED2(Text, QString, Widget::weak_ptr);

			/**
			 * Destroy this Text Widget.
			 */
			virtual ~Text();



			/**
			 * Get the text.
			 */
			QString text() const;

			/**
			 * Set the text.
			 *
			 * @param text    the new text to display
			 * @param force   use this flag to force recalculating a new size
			 */
			void setText(const QString& text, bool force = false);

			/**
			 * Append something to the text.
			 */
			void appendText(const QString& text);
			void appendText(QChar c);

			/**
			 * Prepend something to the text.
			 */
			void prependText(const QString& text);
			void prependText(QChar c);



			/**
			 * Get the font for this text.
			 */
			const FontDesc& fontDesc() const;



			/**
			 * Get the color of the text.
			 */
			const math::color& color() const;



			/**
			 * Get the alignment of this widget's text.
			 */
			HAlignment::Type horizontalAlignment() const;

			/**
			 * Set the alignment of this widget's text.
			 */
			void setHorizontalAlignment(HAlignment::Type alignment);

			/**
			 * Get the alignment of this widget's text.
			 */
			VAlignment::Type verticalAlignment() const;

			/**
			 * Set the alignment of this widget's text.
			 */
			void setVerticalAlignment(VAlignment::Type alignment);



			/**
			 * Get the vertical flow of this widget's text.
			 */
			VFlow::Type verticalFlow() const;

			/**
			 * Set the vertical flow of this widget's text.
			 */
			void setVerticalFlow(VFlow::Type verticalFlow);



			/**
			 * Updates the widget, based on the current state.
			 * All widgets will be updated, no matter what their current state is.
			 */
			virtual void update(NestedState& state);



			/**
			 * Extracts the entire FontDescription from the given
			 * widget style.
			 */
			static FontDesc fontDesc(const WidgetStyle::ptr& style, WidgetState::Type state);

		protected:

			/**
			 * Get the type of this widget.
			 */
			virtual Widgets::Type type() const;

			/**
			 * This function is bound to the stateChanged() signal and requests the current
			 * font description that should be used by this widget.
			 */
			void onStateChanged(Widget::weak_ptr that);

			/**
			 * Creates the quads that are required to display the text.
			 */
			virtual void renderAdditional(Quads& quads, const NestedState& state);

			/**
			 * Get the number of quads, this text is composed of.
			 * The returned number may be used until the state of this text is changed.
			 * Then it must be recalculated.
			 */
			virtual uint32 numAdditionalQuads() const;

		private:

			/**
			 * Depending on the current settings, calculate the
			 * required size of this text-widget.
			 */
			intsize2 calculateSize() const;

		private:

			/// The displayed text
			QString            m_text;

			/// The color of the text
			math::color        m_fontColor;

			/// The description of the current font
			FontDesc           m_fontDesc;


			/// The cache that is used to store all qauds, once rendered
			Cache<Quads>       m_cache;


			/// Defines what kind of alignment is used
			HAlignment::Type   m_horizontalAlignment;

			/// Defines what kind of alignment is used
			VAlignment::Type   m_verticalAlignment;

			/// The vertical flow of the text
			VFlow::Type        m_verticalFlow;

			/// The horizontal flow of the text
			HFlow::Type        m_horizontalFlow;
		};
		///////////////////////////////////////////////////////////////////////////////////////////
	}
	///////////////////////////////////////////////////////////////////////////////////////////////
}
///////////////////////////////////////////////////////////////////////////////////////////////////
